"""Camera functions for managing the view"""

import math
from numpy import *
from scopiavf.engine.rendertree import RenderCameraNode

class Camera( RenderCameraNode ):
    "Camera class"

    def __init__(self, context, style, child, center, radius, angle):
        """Creates a camera rotating around a 'center' at a distance of
           'radius' and with a height angle of 'angle'."""
        RenderCameraNode.__init__(self, context, style, child)
        self.viewTo = array(center, float32)
        self.radius = array(radius, float32)
        self.hangle = angle
        self.angle = 0.0
        self.angleMove = -1
        self.moveCenterLeft = self.moveCenter = self.moveRadius = self.moveRadiusLeft = None

    def closer(self):
        "Starts a movement to put the camera closer to the rotation center"
        self.moveRadius = array(-1.0,float32)
        self.moveRadiusLeft = abs( self.radius * array(0.8, float32) - self.radius)
        self.moveRadiusSpeed = array(2.0, float32) * self.moveRadiusLeft

    def farer(self): 
        "Starts a movement to put the camera farer to the rotation center"
        self.moveRadius = array(1.0,float32)
        self.moveRadiusLeft = abs( self.radius * array(1.3, float32) - self.radius)
        self.moveRadiusSpeed = array(2.0, float32) * self.moveRadiusLeft

    def update( self , time):
        "Uses the movement vectors and speeds to update camera position and target"
        if self.angleMove < 0 and self.angle <= -math.pi: self.angleMove = 1
        elif self.angleMove > 0 and self.angle >= 0: self.angleMove = -1
        aspeed = max( min( 0.05, abs(-math.pi - self.angle)*1.0, abs( 0 - self.angle) * 1.0 ), 0.005)
        self.angle += time * aspeed * self.angleMove
        if self.moveCenter != None:
            l = array(time, float32) * self.moveCenterSpeed
            if l >= self.moveCenterLeft: 
                l = self.moveCenterLeft
                self.moveCenterLeft = 0.0
            else: self.moveCenterLeft -= l
            self.viewTo = self.viewTo + self.moveCenter*l
            if not self.moveCenterLeft:
                self.moveCenterLeft = None
                self.moveCenter = None
        if self.moveRadius != None:
            l = array(time, float32) * self.moveRadiusSpeed
            if l >= self.moveRadiusLeft:
                l = self.moveRadiusLeft
                self.moveRadiusLeft = 0.0
            else: self.moveRadiusLeft -= l
            self.radius = self.radius + self.moveRadius*l
            if not self.moveRadiusLeft:
                self.moveRadiusLeft = None
                self.moveRadius = None
        a = self.angle
        V = array( ( math.cos(a), math.sin(a), math.sin(self.hangle) ), float32 )
        self.viewFrom = self.viewTo + V*self.radius
        self.clipStart = 0.1*self.radius
        self.clipEnd = 12.0*self.radius

    def goTo(self, center, radius):
        "Starts a movement to put the camera over the given center at the given radius"
        self.moveCenter = center - self.viewTo
        self.moveCenterLeft = sqrt(dot(self.moveCenter,self.moveCenter))
        self.moveCenterSpeed = array(0.5, float32) * self.moveCenterLeft
        if self.moveCenter.any():
            self.moveCenter *= array(1.0,float32) / self.moveCenterLeft
        if radius > self.radius: self.moveRadius = array(1.0,float32)
        else: self.moveRadius = array(-1.0,float32)
        self.moveRadiusLeft = abs(array(radius,float32) - self.radius)
        self.moveRadiusSpeed = array(0.5, float32) * self.moveRadiusLeft
        
